package com.three.netty.rocketmq;

import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.Message;
import com.three.api.protocol.Packet;
import com.three.api.service.BaseService;
import com.three.api.service.Listener;
import com.three.config.common.IConfig;
import com.three.utils.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.three.config.common.IConfig.chess.rocket_mq.namesrv_addr;
import static com.three.config.common.IConfig.chess.rocket_mq.producer_group_name;

/**
 * 消息队列生产者
 * Created by Mathua on 2017/6/27.
 */
public class MQProducerService extends BaseService {

    public static final MQProducerService I = new MQProducerService(producer_group_name, IConfig.chess.rocket_mq.topic, IConfig.chess.rocket_mq.tag);
    private final String topic;
    private final String tag;

    private static final Logger LOGGER = LoggerFactory.getLogger(MQProducerService.class);

    /**
     * 一个应用创建一个Producer，由应用来维护此对象，可以设置为全局对象或者单例<br>
     * 注意：ProducerGroupName需要由应用来保证唯一<br>
     * ProducerGroup这个概念发送普通的消息时，作用不大，但是发送分布式事务消息时，比较关键，
     * 因为服务器会回查这个Group下的任意一个Producer
     */
    private final DefaultMQProducer producer;/* = new DefaultMQProducer("ProducerGroupName");*/
    public MQProducerService(String producerGroupName, String topic, String tag) {
        producer = new DefaultMQProducer(producerGroupName);
        this.topic = topic;
        this.tag = tag;
    }

    @Override
    protected void doStart(Listener listener) throws Throwable {
        producer.setNamesrvAddr(namesrv_addr);
        producer.setInstanceName("Producer");
        producer.setVipChannelEnabled(false);
        /**
         * Producer对象在使用之前必须要调用start初始化，初始化一次即可<br>
         * 注意：切记不可以在每次发送消息时，都调用start方法
         */
        producer.start();
        LOGGER.info("ProducerStarted.");
        listener.onSuccess();
    }

    @Override
    protected void doStop(Listener listener) throws Throwable {
        /**
         * 应用退出时，要调用shutdown来清理资源，关闭网络连接，从MetaQ服务器上注销自己
         * 注意：我们建议应用在JBOSS、Tomcat等容器的退出钩子里调用shutdown方法
         */
        producer.shutdown();
        LOGGER.info("ProducerShutdown.");
        listener.onSuccess();
    }

    /**
     * 发送给玩家
     * @param receiverId 接收者id
     * @param packet 要发送的数据包
     * @return
     */
    public SendResult sendToPlayer(long receiverId, Packet packet) {
        try {
            return producer.send(new Message(topic, tag, MQKeys.SEND_TO_PLAYER.keys + receiverId, ObjectUtils.toBytes(packet)));
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            return null;
        }
    }
}
